package main

import (
	"bytes"
	"errors"
	"fmt"
	"os/exec"

	"image"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/chai2010/webp"
	"github.com/nfnt/resize"
	log "github.com/sirupsen/logrus"
	"golang.org/x/image/bmp"
)

// func convertImage(raw, optimizedPath, itype string, size *Resize) {

// 	s := strings.Split(path.Base(optimizedPath), ".")
// 	pattern := path.Join(path.Dir(optimizedPath), s[0]+"."+s[1]+".*."+s[3]+"."+s[len(s)-1])
// 	fmt.Printf(pattern)
// 	matches, err := filepath.Glob(pattern)
// 	if err != nil {
// 		log.Error(err.Error())
// 	} else {
// 		for _, p := range matches {
// 			_ = os.Remove(p)
// 		}
// 	}
// 	//we need to create dir first
// 	err = os.MkdirAll(path.Dir(optimizedPath), 0755)
// 	//q, _ := strconv.ParseFloat(config.Quality, 32)

// 		webpEncoder(img, optimizedPath, size)
// 	}
// }
// func webpEncoder(img image.Image, p2 string, size *Resize) {
// 	var buf bytes.Buffer

// 	err := webp.Encode(&buf, img, &webp.Options{Lossless: false, Quality: float32(size.Quality)})
// 	if err != nil {
// 		log.Warnf("Can't encode source image: %v to WebP", err)
// 	}

// 	if err := ioutil.WriteFile(p2, buf.Bytes(), 0644); err != nil {
// 		log.Error(err)
// 		return
// 	}
// }

/**压缩并保存图片
 */
func compressImage(imgPath string, baseOutFilenamePath string, outWebpFilePath string, size *Resize) (err error) {
	data, err := ioutil.ReadFile(imgPath)
	if err != nil {
		log.Errorln(err)
	}
	var img image.Image
	contentType := getFileContentType(data[:512])
	ImageType := ""
	if strings.Contains(contentType, "jpeg") {
		ImageType = "jpeg"
		img, err = jpeg.Decode(bytes.NewReader(data))
	} else if strings.Contains(contentType, "png") {
		ImageType = "png"
		img, err = png.Decode(bytes.NewReader(data))
	} else if strings.Contains(contentType, "bmp") {
		ImageType = "bmp"
		img, err = bmp.Decode(bytes.NewReader(data))
	} else if strings.Contains(contentType, "gif") {
		ImageType = "gif"
		if !imageExists(outWebpFilePath) {
			fmt.Println("gif转码路径", imgPath, outWebpFilePath)

			err := os.MkdirAll(path.Dir(outWebpFilePath), 0755)
			if err != nil {
				log.Error(err)
				return errors.New("创建目录失败")
			}
			cmd := exec.Command("./gif2webp", "-lossy", "-q", fmt.Sprint(size.Quality), imgPath, "-o", outWebpFilePath)
			cmdBuf, err := cmd.Output()
			if err != nil {
				fmt.Println(err.Error())
			}
			fmt.Println("gif转码", string(cmdBuf))
		}

		// var miniGif *gif.GIF
		// if !imageExists(baseOutFilenamePath) {
		// 	gifIMG, giferr := gif.DecodeAll(bytes.NewReader(data))

		// 	if giferr != nil {
		// 		return errors.New("errinfo:gif解码失败")
		// 	}
		// 	miniGif, _ = resizeGif(gifIMG, size.Width, size.Height)
		// 	var buf bytes.Buffer
		// 	err := gif.EncodeAll(&buf, miniGif)
		// 	if err != nil {
		// 		fmt.Println("gif.EncodeAll", err)
		// 		return err
		// 	}
		// 	gifBin := buf.Bytes()
		// 	WriteFile(baseOutFilenamePath, gifBin) // 保存缩小的gif
		// } else {

		// 	//有损压缩
		// 	cmd := exec.Command("./gif2webp", "-lossy", baseOutFilenamePath, "-o", outWebpFilePath)
		// 	cmdBuf, err := cmd.Output()
		// 	if err != nil {
		// 		fmt.Println(err.Error())
		// 	}
		// 	fmt.Println(string(cmdBuf))
		// }

		// cmd := exec.Command("./gif2webp", baseOutFilenamePath, "-o", outWebpFilePath)
		// cmdBuf, err := cmd.Output()
		// if err != nil {
		// 	fmt.Println(err.Error())
		// }
		// fmt.Println(string(cmdBuf))

		// 对gif转webp
		// webpGifImg, err := gifToWebPFn(miniGif, size.Quality)
		// if err != nil {
		// 	return err
		// }
		// WriteFile(outWebpFilePath, webpGifImg)

		return nil
	}
	if err != nil || img == nil {
		errinfo := fmt.Sprintf("解码图片 %s 失败: %v", imgPath, err)
		log.Errorln(errinfo)
		return errors.New(errinfo)
	}

	var maxWidth, maxHeight uint

	if size.Width > 0 && size.Height > 0 && (size.Width < webpMax || size.Height < webpMax) {
		maxWidth = size.Width
		maxHeight = size.Height
	} else {
		maxWidth = webpMax
		maxHeight = webpMax
	}
	miniImg, err := MakeThumbnail(data, ImageType, maxWidth, maxHeight)

	if !imageExists(baseOutFilenamePath) {
		SaveImage(miniImg, baseOutFilenamePath, ImageType, size)
	}
	if !imageExists(outWebpFilePath) {
		SaveImage(miniImg, outWebpFilePath, "webp", size)
	}
	return err

}

/**
创建缩略图
*/
func MakeThumbnail(Data []byte, ImageType string, width uint, height uint) (out image.Image, err error) {
	var img image.Image

	reader := bytes.NewReader(Data)
	// reader2 := bytes.NewReader(Data)
	switch ImageType {
	case "jpeg":
		img, _ = jpeg.Decode(reader)
		break
	case "png":
		img, _ = png.Decode(reader)
		break
	case "bmp":
		img, _ = bmp.Decode(reader)
		break
	case "gif":
		// 这里不对gif压缩
	}
	if img == nil {
		msg := "不支持压缩的文件类型"
		err = errors.New(msg)
		return nil, err
	}
	if ImageType == "gif" {
		return img, nil
	}
	miniImg := resize.Thumbnail(width, height, img, resize.Lanczos3)

	return miniImg, nil
}

/**
改变gif的长宽
*/
func resizeGif(im *gif.GIF, width uint, height uint) (out *gif.GIF, err error) {
	// reader := bytes.NewReader(Data)
	// im, err := gif.DecodeAll(reader)
	if err != nil {
		return nil, err
	}
	// reset the gif width and height
	im.Config.Width = int(width)
	im.Config.Height = int(height)

	firstFrame := im.Image[0].Bounds()
	img := image.NewRGBA(image.Rect(0, 0, firstFrame.Dx(), firstFrame.Dy()))

	// resize frame by frame
	for index, frame := range im.Image {
		b := frame.Bounds()
		draw.Draw(img, b, frame, b.Min, draw.Over)
		im.Image[index] = imageToPaletted(resize.Resize(uint(width), uint(height), img, resize.NearestNeighbor))
	}
	return im, nil
}
func imageToPaletted(img image.Image) *image.Paletted {
	b := img.Bounds()
	pm := image.NewPaletted(b, palette.Plan9)
	draw.FloydSteinberg.Draw(pm, b, img, image.ZP)
	return pm
}

// func gifToWebPFn(gifBin *gif.GIF, quality uint) (webPBin []byte, err error) {

// }

func SaveImage(img image.Image, imgPath string, ImageType string, size *Resize) error {
	// 文件已存在
	if imageExists(imgPath) {
		return errors.New("文件已存在")
	}

	buffer := new(bytes.Buffer)
	var err error
	switch ImageType {
	case "jpeg":
		err = jpeg.Encode(buffer, img, &jpeg.Options{Quality: int(size.Quality)})
		break
	case "png":
		err = png.Encode(buffer, img)
		break
	case "bmp":
		err = bmp.Encode(buffer, img)
		break
	case "gif":

		break
	case "webp":
		err = webp.Encode(buffer, img, &webp.Options{Lossless: false, Quality: float32(size.Quality)})
	}
	if err != nil {
		log.Error("转码失败", err)
		return errors.New("文件已存在")
	}
	// if ImageType == "gif" {
	// 	return ioutil.WriteFile(imgPath, buffer.Bytes(), 0644)
	// 	// return nil
	// }
	WriteFile(imgPath, buffer.Bytes())
	return nil
}
func WriteFile(filePath string, data []byte) error {
	err := os.MkdirAll(path.Dir(filePath), 0755)
	if err != nil {
		log.Error(err)
		return errors.New("创建目录失败")
	}
	if err := ioutil.WriteFile(filePath, data, 0644); err != nil {
		log.Error(err)
		return errors.New("写入失败")
	}
	return nil
}
